// -*- C++ -*------------------------------------------------------------------
// $Id: XyzSaver.cc,v 1.2 2007-10-26 14:55:23 biocomp Exp $
//
//  Class:             XyzSaver
//
//  Base Class(es):    Saver
//
//  Derived Class(es): -
//
//  Containing:        -
//
//  Author:            Silvio Tosatto
//
//  Project Name:      Victor
//
//  Date:              08/99
//
//  Reviewed By:       <Name>
//
//  Description:
//    Saves components (Atoms, Groups, etc.) in XYZ (carthesian) format.
//    Internal format is made of type, coords & bonds of each atom,
//    one per line. Keywords "aminoacid" and "sidechain" delimit these
//    structures.
//
// ---------------------------------------------------------------------------

// Includes:
#include <XyzSaver.h>
#include <IoTools.h>
#include <vector3.h>

// Global constants, typedefs, etc. (to avoid):

using namespace Biopool;


// CONSTRUCTORS/DESTRUCTOR:


// MODIFIERS:

// -*- C++ -*-----------------------------------------------------------------
//
//  Method:        XyzSaver::saveGroup
//
//  Author:        Silvio Tosatto 
//
//  Date:          09/99
//
//  Description:
//    Saves a group in xyz format. 
//
// ----------------------------------------------------------------------------
void 
XyzSaver::saveGroup(Group& gr)
{  
  PRINT_NAME;
  gr.sync();
  output << gr.getType() << "\n";
  pSaveAtomVector(gr.giveAtoms()); 
}

// -*- C++ -*-----------------------------------------------------------------
//
//  Method:        XyzSaver::saveSideChain
//
//  Author:        Silvio Tosatto 
//
//  Date:          09/99
//
//  Description:
//    Saves a sidechain in xyz format. 
//
// ----------------------------------------------------------------------------
void 
XyzSaver::saveSideChain(SideChain& sc)
{
  PRINT_NAME;
  sc.sync();
  if (delimit)
    output << sc.getType() << "\n";
  pSaveAtomVector(sc.giveAtoms()); 
}

// -*- C++ -*-----------------------------------------------------------------
//
//  Method:        XyzSaver::saveAminoAcid
//
//  Author:        Silvio Tosatto 
//
//  Date:          09/99
//
//  Description:
//    Saves an aminoacid in xyz format. 
//
// ----------------------------------------------------------------------------
void 
XyzSaver::saveAminoAcid(AminoAcid& aa)
{
  PRINT_NAME;
  aa.sync();
  if (delimit)
    output << aa.getType() << "\n";
  pSaveAtomVector(aa.giveAtoms()); 
  if (delimit)
    output << "  sidechain\n  ";
  saveSideChain(aa.getSideChain());
}

// -*- C++ -*-----------------------------------------------------------------
//
//  Method:        XyzSaver::saveSpacer
//
//  Author:        Silvio Tosatto 
//
//  Date:          09/99
//
//  Description:
//    Saves a spacer in xyz format. 
//
// ----------------------------------------------------------------------------
void 
XyzSaver::saveSpacer(Spacer& sp)
{
  PRINT_NAME;
  //  sp.sync();
  if (delimit)
    output << sp.getType() << "\n";
  else
    {  // write number of atoms
      unsigned int size = 0;
      for (unsigned int i = 0; i < sp.sizeAmino(); i++)
	size += sp.getAmino(i).size();
      output << size << "\n\n";
    }
  for (unsigned int i = 0; i < sp.size(); i++)
    {
      if (delimit)
	output << "aminoacid\n";
      sp[i].save(*this);
    }
}

// -*- C++ -*-----------------------------------------------------------------
//
//  Method:        XyzSaver::saveLigand
//
//  Author:        Marcus Pruemmer
//
//  Date:          06/2000
//
//  Description:
//    Saves a Ligand in xyz format. 
//
// ----------------------------------------------------------------------------
void 
XyzSaver::saveLigand(Ligand& l)
{
  PRINT_NAME;
  ERROR("Not implemented yet",exception);
}

// HELPER:

// -*- C++ -*-----------------------------------------------------------------
//
//  Method:        XyzSaver::pSaveAtomVector
//
//  Author:        Silvio Tosatto 
//
//  Date:          09/99
//
//  Description:
//    Private helper method to save a vector of atoms.
//    Attention: ID realignment is currently commented out.
//
// ----------------------------------------------------------------------------
void 
XyzSaver::pSaveAtomVector(vector<Atom>& va)
{  // warning: don't copy atom vector as it would lose the original bonds
  unsigned old_prec = output.precision();
  ios::fmtflags old_flags = output.flags();
  output.setf(ios::fixed, ios::floatfield);

//    vector<int> tmpVA;
//    for (unsigned int i = 0; i < va.size(); i++)
//      {
//        tmpVA.push_back(va[i].getNumber());
//        va[i].setNumber(i + offset);  // realign IDs for saving (optional)
//      }
//    int tmp1 = 101;
//    int tmp2 = 901;
  for (unsigned int k = 0; k < va.size(); k++)  // write all entries
    {
      string atName = va[k].getType();
      if (!isdigit(atName[0]))
	atName = ' ' + atName;
      while (atName.size() < 4)
	atName += ' ';

      if (delimit)
	output << "  " << setw(4) << va[k].getNumber() << "   ";
      output << atName << "  " << va[k].getCoords() << "   ";
      for (unsigned int i = 0; i < va[k].sizeInBonds(); i++)
//  	if (va[k].getInBond(i).getNumber() > va.size()+offset)
//  	    output << "\t" << setw(3) << (tmp1++)
//  		   << " " << va[k].getInBond(i).getType();
//  	else
	  output << "   " << setw(3) << va[k].getInBond(i).getNumber();
      for (unsigned int i = 0; i < va[k].sizeOutBonds(); i++)
//  	if (va[k].getOutBond(i).getNumber() > va.size()+offset)
//  	  output << "\t" << setw(3) << (tmp2++) 
//  		 << " " << va[k].getOutBond(i).getType();
//  	else
	  output << "   " << setw(3) << va[k].getOutBond(i).getNumber();
      output << "\n";
    }
//    for (unsigned int i = 0; i < va.size(); i++)
//      va[i].setNumber(tmpVA[i]);  // return IDs as before
  output.precision(old_prec);
  output.flags(old_flags);
}

